package kiwi.assist.dev.guieditor.command {
	import kiwi.assist.dev.guieditor.model.format.IValueFormat;

	import fl.managers.StyleManager;

	import ghostcat.gxml.spec.ItemSpec;
	import ghostcat.gxml.spec.Spec;
	import ghostcat.util.ReflectUtil;

	import kiwi.assist.dev.guieditor.event.GUIEditorEvent;
	import kiwi.assist.dev.guieditor.model.ContainerConfig;
	import kiwi.assist.dev.guieditor.model.EnumConfig;
	import kiwi.assist.dev.guieditor.model.GUIEditorConfig;
	import kiwi.assist.dev.guieditor.model.PropertyConfig;
	import kiwi.assist.dev.guieditor.model.StyleConfig;
	import kiwi.assist.dev.guieditor.model.StyleLibConfig;
	import kiwi.assist.dev.guieditor.model.UiConfig;
	import kiwi.assist.dev.guieditor.model.format.BooleanFormat;
	import kiwi.assist.dev.guieditor.model.format.ClassFormat;
	import kiwi.assist.dev.guieditor.model.format.DataProviderFormat;
	import kiwi.assist.dev.guieditor.model.format.FilterFormat;
	import kiwi.assist.dev.guieditor.model.format.JsonFormat;
	import kiwi.assist.dev.guieditor.model.format.NumericFormat;
	import kiwi.assist.dev.guieditor.model.format.SkinFormat;
	import kiwi.assist.dev.guieditor.model.format.StringFormat;
	import kiwi.assist.dev.guieditor.model.format.StyleFormat;
	import kiwi.assist.dev.guieditor.model.format.TFFormat;
	import kiwi.assist.dev.reflect.UiComponentSpec;
	import kiwi.util.asserts.assert;
	import kiwi.util.bitmap.BitmapPool;

	import org.robotlegs.mvcs.Command;

	import flash.display.DisplayObject;

	/**
	 * 初始化gui的配置
	 * @author zhangming.luo
	 */
	public class InitGUIEditorConfigCommand extends Command {
		[Inject]
		public var event : GUIEditorEvent;
		[Inject]
		public var config : GUIEditorConfig;
		/**
		 * 所有的配置XML文档
		 */
		private var configXML : XML;

		override public function execute() : void {
			super.execute();
			configXML = XML(event.data);
			// 解析所有的配置
			parseStyleLib();
			parseStyleSheet();
			parseEnummap();
			parseContainer();
			parseUi();
			dispatch(new GUIEditorEvent(GUIEditorEvent.CONFIG_CHANGE));
		}

		private function parseEnummap() : void {
			for each (var enums:XML in configXML.enummap.enums) {
				var name : String = enums.@name;
				var format : IValueFormat;
				switch(String(enums.@format)) {
					case "DataProvider":
						format = new DataProviderFormat();
						break;
					case "Numeric":
						format = new NumericFormat();
						break;
					case "String":
						format = new StringFormat();
						break;
					case "Boolean":
						format = new BooleanFormat();
						break;
					case "Skin":
						format = new SkinFormat();
						break;
					case "Json":
						format = new JsonFormat();
						break;
					default:
						assert(false, "未知的数据类型 " + format);
				}
				var array : Array = [];
				for each (var enum:XML in enums.enum) {
					var enumConfig : EnumConfig = new EnumConfig(String(enum.@name), format.getValueByInput(String(enum.text())));
					if (format is JsonFormat) {
						var spec : Spec = new Spec();
						enumConfig.value = spec.createObject(XML(enum.toXMLString()))[0];
					}
					array.push(enumConfig);
				}
				EnumConfig.addEnum(name, array);
			}
		}

		/**
		 * 默认样式
		 */
		private function parseStyleSheet() : void {
			var baseUrl : String = configXML.stylesheet.BitmapPool.@baseUrl;
			if (baseUrl) {
				config.uiPrefix = configXML.stylesheet.BitmapPool.@uiPrefix;
				var fileExtension : String = configXML.stylesheet.BitmapPool.@fileExtension;
				BitmapPool.baseURL = baseUrl;
				if (fileExtension) {
					BitmapPool.fileExtension = fileExtension;
				}
				StyleManager.registerPool(function(uri : *) : DisplayObject {
					return BitmapPool.getBitmap(config.uiPrefix + "/" + uri);
				});
			}
			for each (var style:XML in configXML.stylesheet.style) {
				var styleConfig : StyleConfig = new StyleConfig();
				styleConfig.key = style.@name;
				styleConfig.target = style.@target;
				var spec : ItemSpec = new ItemSpec();
				styleConfig.value = UiComponentSpec.readStyleValue(style, spec.createObject(style));
				if (styleConfig.target) {
					StyleManager.setComponentStyle(ReflectUtil.getClass(styleConfig.target), styleConfig.key, styleConfig.value);
				} else {
					StyleManager.setStyle(styleConfig.key, styleConfig.value);
				}
			}
		}

		/**
		 * 容器
		 */
		private function parseContainer() : void {
			var defaultContainer : String = configXML.container.@default;
			for each (var xml:XML in configXML.container.component) {
				var container : ContainerConfig = new ContainerConfig();
				container.name = xml.@name;
				container.className = xml.@className;
				container.leftPadding = xml.@leftPadding;
				container.rightPadding = xml.@rightPadding;
				container.topPadding = xml.@topPadding;
				container.bottomPadding = xml.@bottomPadding;
				container.comp = xml.@comp;
				container.factoryClz = String(xml.factory.@clz);
				container.defaultConfig = xml.factory.children()[0];
				xml.property[0] && readProperty(container.propertyList, xml.property[0]);
				xml.style[0] && readStyles(container, xml.style[0]);
				config.containers.push(container);
				config.uis.push(container);
				if (defaultContainer == container.comp) {
					config.defaultContainer = container;
				}
			}
		}

		private function parseUi() : void {
			var xml : XML;
			var ui : UiConfig;
			for each (xml in configXML.ui.component) {
				ui = new UiConfig();
				ui.name = xml.@name;
				ui.comp = xml.@comp;
				ui.type = xml.@type;
				ui.className = xml.@className;
				ui.hide = Boolean(String(xml.@hide));
				ui.factoryClz = String(xml.factory.@clz);
				ui.defaultConfig = xml.factory.children()[0];
				if (xml.attribute("override").length() > 0 && Boolean(String(xml.attribute("override")[0]))) {
					// 寻找并替换已有的
					if (!config.uis.some(function(item : UiConfig, index : int, array : *) : Boolean {
						if (item.comp == ui.comp) {
							// 需要覆盖了
							array[index] = ui;
							return true;
						}
						return false;
					})) {
						// 没有找到需要覆盖的
						config.uis.push(ui);
					}
				} else {
					// 同名的新控件
					config.uis.push(ui);
				}
				// 读取ui的属性
				if (XMLList(xml.property).length()) {
					readProperty(ui.propertyList, xml.property[0]);
				}
				// 读取ui的样式
				if (XMLList(xml.style).length()) {
					readStyles(ui, xml.style[0]);
				}
			}
		}

		private function readStyles(ui : UiConfig, style : XML) : void {
			for each (var info:XML in style.children()) {
				ui.styleList.push(readStyle(info));
			}
		}

		private function readStyle(info : XML) : StyleConfig {
			var styleConfig : StyleConfig = new StyleConfig();
			styleConfig.key = info.localName();
			styleConfig.nopublish = Boolean(String(info.@nopublish));
			switch(String(info.@format)) {
				case "Numeric":
					styleConfig.format = new NumericFormat();
					break;
				case "Boolean":
					styleConfig.format = new BooleanFormat();
					break;
				case "String":
					styleConfig.format = new StringFormat();
					break;
				case "Filter":
					styleConfig.format = new FilterFormat();
					break;
				case "Style":
					styleConfig.format = new StyleFormat();
					break;
				case "Class":
					styleConfig.format = new ClassFormat();
					styleConfig.className = String(info.@className);
					break;
				case "Skin":
					styleConfig.format = new SkinFormat();
					break;
				case "TextFormat":
					styleConfig.format = new TFFormat();
					styleConfig.className = "flash.text.TextFormat";
					break;
			}
			return styleConfig;
		}

		private function readProperty(list : *, property : XML) : void {
			for each (var info:XML in property.children()) {
				var propertyConfig : PropertyConfig = new PropertyConfig();
				propertyConfig.key = info.localName();
				propertyConfig.readOnly = Boolean(String(info.@readOnly));
				propertyConfig.nopublish = Boolean(String(info.@nopublish));
				assert(info.attribute("format").length() > 0, "没有指定format " + propertyConfig.key);
				var format : String = String(info.@format);
				switch(format) {
					case "DataProvider":
						propertyConfig.format = new DataProviderFormat();
						break;
					case "Numeric":
						propertyConfig.format = new NumericFormat();
						break;
					case "String":
						propertyConfig.format = new StringFormat();
						break;
					case "Boolean":
						propertyConfig.format = new BooleanFormat();
						break;
					case "Skin":
						propertyConfig.format = new SkinFormat();
						break;
					case "Json":
						propertyConfig.format = new JsonFormat();
						break;
					default:
						assert(false, "未知的数据类型 " + format);
				}
				if (String(info.@enum) == "true") {
					// 有枚举的说
					if (String(info.@enumRef)) {
						propertyConfig.enumList = EnumConfig.byName(info.@enumRef);
					} else {
						for each (var enumInfo:XML in info..enum) {
							var enumConfig : EnumConfig = new EnumConfig(String(enumInfo.@name), propertyConfig.format.getValueByInput(String(enumInfo.text())));
							propertyConfig.enumList.push(enumConfig);
							if (propertyConfig.format is JsonFormat) {
								var spec : Spec = new Spec();
								enumConfig.value = spec.createObject(XML(enumInfo.toXMLString()))[0];
							}
						}
					}
				}
				propertyConfig.defaultValue = info.@default;
				list.push(propertyConfig);
			}
		}

		private function parseStyleLib() : void {
			while (config.styles.length) {
				config.styles.pop();
			}
			for each (var xml:XML in configXML.style_libs.lib) {
				var style : StyleLibConfig = new StyleLibConfig();
				style.name = xml.@name;
				style.src = xml.@src;
				config.styles.push(style);
			}
		}
	}
}
